package peer.rdp;

import java.util.HashMap;
import java.util.Iterator;

import peer.Config;
import peer.rdp.message.AskFillMessage;


public class AskFillMange implements Runnable{
	Connection conn;
	HashMap<Long, TaskBox> boxTable;
	HashMap<TaskIdent, BoxTable> taskBoxMap;
	boolean haveTask=false;
	Object signalOb=new Object();
	Thread mainThread;
	long vTime=0;
	long lastReSendTime;
	public AskFillMange(){
		boxTable=new HashMap<Long, TaskBox>(1024);
		taskBoxMap=new HashMap<TaskIdent, BoxTable>(1024);
		mainThread=new Thread(this);
		mainThread.start();
	}
	
	public synchronized void addTask(Connection conn,int sequence){
		TaskIdent ti=new TaskIdent(conn,sequence);
		if(!taskBoxMap.containsKey(ti)){
			BoxTable bt=new BoxTable();
			taskBoxMap.put(ti, bt);
		}
		BoxTable bt=taskBoxMap.get(ti);
		for(int i=0;i<Config.reFillTryTimes;i++){
			long  boxNum=vTime+(i+1)*Config.reFillMessageDelay1;
			if(i==0){
				boxNum=vTime+Config.reFillMessageDelay2;
			}
			if(!boxTable.containsKey(boxNum)){
				TaskBox tb=new TaskBox(boxNum);
				boxTable.put(boxNum,tb);
			}
			TaskBox tb=boxTable.get(boxNum);
			tb.hm.put(ti, bt);
			bt.hm.put(boxNum,tb );
		}
		//System.out.println("addAskFill "+sequence+" "+System.currentTimeMillis());
	}
	
	public synchronized boolean containsTask(Connection conn,int sequence){
		TaskIdent ti=new TaskIdent(conn,sequence);
		return taskBoxMap.containsKey(ti);
	}
	
	public synchronized void removeTask(Connection conn,int sequence){
		TaskIdent ti=new TaskIdent(conn,sequence);
		BoxTable bt=taskBoxMap.get(ti);
		if(bt!=null){
			Iterator it = bt.hm.keySet().iterator();
			while ( it.hasNext()){
				long boxNum = (Long)it.next();
				TaskBox tb=bt.hm.get(boxNum);
				tb.hm.remove(ti);
				if(tb.hm.size()==0){
					boxTable.remove(boxNum);
				}
			}
		}
		taskBoxMap.remove(ti);
	}
	
	public void run() {
		while(true){
			long boxNum=vTime;
			TaskBox tb=boxTable.get(boxNum);
			synchronized(this){
				if(tb!=null){
					Iterator it = tb.hm.keySet().iterator();
					while(it.hasNext()){
						TaskIdent ti=(TaskIdent)it.next();
						AskFillMessage rfm=new AskFillMessage(ti.conn,ti.sequence);
						if(ti.conn.isConnected()){
							if(rfm.getSequence()>ti.conn.receiver.lastRead2){}
							if(ti.conn.sender.unAckTable.containsKey(ti.sequence)){
								rfm.setDstAddress(ti.conn.dstIp);
								rfm.setDstPort(ti.conn.dstPort);
								ti.conn.sender.sendAskFillMessage(rfm);
								ti.conn.receiver.reduceWin();
							}
						}
						BoxTable mp=(taskBoxMap.get(ti));
						mp.hm.remove(boxNum);
						if(mp.hm.size()==0){
							taskBoxMap.remove(ti);
						}
					}
					boxTable.remove(boxNum);
				}
			}
			try {
				Thread.sleep(1);
				vTime++;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	void viewBoxTable(){
		//System.out.println("VIEW BOXTABLE");
		Iterator<Long> it=boxTable.keySet().iterator();
		while(it.hasNext()){
			//System.out.print("box num ");
			long boxNum=it.next();
			TaskBox tb=boxTable.get(boxNum);
			Iterator it2=tb.hm.keySet().iterator();
			while(it2.hasNext()){
				@SuppressWarnings("unused")
				TaskIdent ti=(TaskIdent) it2.next();
			}
		}
	}
}
